Skip to content

Conversation

@asithade
Copy link
Contributor

@asithade asithade commented Dec 1, 2025

Summary

  • Add company bus factor API integration for foundation health dashboard
  • Add event attendance monthly API with cumulative trend data
  • Add foundation filtering to organization maintainers, contributors, and certified employees endpoints
  • Add monthly trend charts to organization involvement dashboard metrics
  • Improve UI polish with hover states, distinct chart colors, and updated button styles

Changes

API Endpoints

  • GET /api/analytics/company-bus-factor - Foundation company bus factor data
  • GET /api/analytics/event-attendance-monthly - Organization event attendance with monthly trends
  • Updated GET /api/analytics/organization-maintainers to require foundationSlug
  • Updated GET /api/analytics/organization-contributors to require foundationSlug
  • Updated GET /api/analytics/certified-employees to use foundationSlug instead of projectSlug

Frontend - Dashboard Metrics

  • Foundation health dashboard now uses live API data for company bus factor
  • Organization involvement dashboard displays monthly trend charts
  • Updated UI colors for bus factor visualization (blue theme)
  • Handle empty foundation selection gracefully
  • Hide membership tier filter on non-all tabs
  • Format Contributors Mentored tooltip dates to match Active Contributors format

Frontend - UI Polish

  • Add hover border effects to meeting cards (blue highlight on hover)
  • Add hover border effects to pending actions with color-specific borders
  • Use distinct colors for organization involvement metric charts:
    • Attendees: emerald
    • Speakers: amber
    • Meetings: violet
  • Update LFX Lens button from solid blue to outlined style with lighter icons
  • Remove redundant Today/Upcoming section headers from meetings list
  • Remove redundant leading-normal from heading styles

Code Quality

  • Remove unused analytics code and interfaces
  • Use committee label constant for dynamic labeling
  • Clean up global SCSS heading styles

Shared Package

  • Added FoundationCompanyBusFactorResponse interface
  • Added OrganizationEventAttendanceMonthlyResponse interface
  • Updated existing interfaces with monthly data arrays
  • Removed hardcoded mock chart data from constants

LFXV2-845

🤖 Generated with Claude Code

- Add company bus factor API integration for foundation health dashboard
- Add event attendance monthly API with cumulative trend data
- Add foundation filtering to organization maintainers, contributors, and certified employees endpoints
- Add monthly trend charts to organization involvement dashboard metrics
- Update interfaces with monthly data arrays
- Remove hardcoded mock chart data from constants

LFXV2-845 LFXV2-846 LFXV2-847 LFXV2-848

Signed-off-by: Asitha de Silva <asithade@gmail.com>
@asithade asithade requested a review from jordane as a code owner December 1, 2025 19:16
Copilot AI review requested due to automatic review settings December 1, 2025 19:16
@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds foundation-scoped monthly trend analytics and company bus-factor endpoints; updates client services, server controllers/routes, organization service queries, shared interfaces/constants, and multiple UI templates/styles to consume monthly-series data and render dynamic bus-factor and chart tooltips.

Changes

Cohort / File(s) Summary
Foundation Health Component
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html, apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
Replaces static company bus-factor with dynamic load via getCompanyBusFactor(foundationSlug) using new signals; updates Data Copilot inputs [includeOrganizationId]="false" and [includeOrganizationName]="false"; adjusts bus-factor bar colors to blue variants.
Organization Involvement Component
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
Migrates event/people flows to monthly response shape (OrganizationEventAttendanceMonthlyResponse), renames initializers to monthly variants, gates fetches on foundationSlug, consumes monthlyData/monthlyLabels for charts and provides fallbacks.
Analytics Service (client)
apps/lfx-one/src/app/shared/services/analytics.service.ts
Adds foundationSlug param to maintainer/contributor/certified methods, introduces getEventAttendanceMonthly(accountId, foundationSlug) and getCompanyBusFactor(foundationSlug), updates error fallbacks to include monthly-series or bus-factor fields, removes getProjects.
Analytics Controller & Routes (server)
apps/lfx-one/src/server/controllers/analytics.controller.ts, apps/lfx-one/src/server/routes/analytics.route.ts
Removes getOrganizationEventsOverview/getProjects endpoints; adds getEventAttendanceMonthly and getCompanyBusFactor controller methods and routes; updates logging and response payloads to include foundation_slug and monthly data fields.
Organization Service (server)
apps/lfx-one/src/server/services/organization.service.ts
Reworks queries to return monthly-trend arrays/labels, extends signatures to accept foundationSlug, adds getEventAttendanceMonthly and getCompanyBusFactor, and exports new monthly-row/response types.
Analytics Interfaces
packages/shared/src/interfaces/analytics-data.interface.ts
Removes consolidated/overview interfaces; adds monthly-row types (CertifiedEmployeesMonthlyRow, OrganizationMaintainersMonthlyRow, OrganizationContributorsMonthlyRow, OrganizationEventAttendanceMonthlyRow), FoundationCompanyBusFactorRow, and FoundationCompanyBusFactorResponse; updates response interfaces to include monthlyData/monthlyLabels and monthly-specific fields.
Dashboard Metrics & Chart Options
packages/shared/src/constants/dashboard-metrics.constants.ts, packages/shared/src/constants/chart-options.constants.ts
Deletes exported COMPANY_BUS_FACTOR, replaces mock involvement chartData with EMPTY_CHART_DATA, introduces BASE_TOOLTIP_STYLE, and refactors tooltip configs (BASE_TOOLTIP_CONFIG, STYLED_TOOLTIP_CONFIG) to reuse base styling.
Data Copilot & Shared UI
apps/lfx-one/src/app/shared/components/data-copilot/data-copilot.component.html
Changes trigger binding from (click) to (onClick), updates button styling and icon markup; drawer structure unchanged.
UI Labeling & Templates
multiple files (committees, meetings, dashboards) e.g., apps/lfx-one/src/app/modules/committees/components/committee-members/*, apps/lfx-one/src/app/modules/meetings/components/*, apps/lfx-one/src/app/modules/dashboards/components/*
Replaces hard-coded committee strings with COMMITTEE_LABEL usages, adds/adjusts hover/transition classes, removes some static section headings, and tweaks pending-actions/meeting card styling; no control-flow changes.
Persona Helper Logging
apps/lfx-one/src/server/utils/persona-helper.ts
Adds request-scoped logging around persona/committee membership checks; functional behavior unchanged.
Styles
apps/lfx-one/src/styles.scss
Removes leading-normal utility from heading rules.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant UI as Dashboard UI
    participant Client as Analytics Service (client)
    participant API as Analytics Controller
    participant OrgSvc as Organization Service
    participant DB as Database

    User->>UI: Open Foundation dashboard
    UI->>Client: getEventAttendanceMonthly(accountId, foundationSlug)
    Client->>API: GET /api/analytics/event-attendance-monthly?accountId&foundationSlug
    API->>OrgSvc: getEventAttendanceMonthly(accountId, foundationSlug)
    OrgSvc->>DB: Query FOUNDATION_EVENT_ATTENDANCE_ORG_MONTHLY
    DB-->>OrgSvc: monthly rows & labels
    OrgSvc-->>API: OrganizationEventAttendanceMonthlyResponse
    API-->>Client: JSON response
    Client-->>UI: Observable with monthly data → render charts

    UI->>Client: getCompanyBusFactor(foundationSlug)
    Client->>API: GET /api/analytics/company-bus-factor?foundationSlug
    API->>OrgSvc: getCompanyBusFactor(foundationSlug)
    OrgSvc->>DB: Query FOUNDATION_COMPANY_BUS_FACTOR
    DB-->>OrgSvc: bus factor rows
    OrgSvc-->>API: FoundationCompanyBusFactorResponse
    API-->>Client: JSON response
    Client-->>UI: Observable → render Bus Factor visualization
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • apps/lfx-one/src/server/services/organization.service.ts — SQL/window-function queries, monthly aggregation correctness, and new exported types.
    • packages/shared/src/interfaces/analytics-data.interface.ts — broad interface renames/shape changes and impact on consumers.
    • apps/lfx-one/src/app/shared/services/analytics.service.ts — updated method signatures and new endpoints; verify client usage sites.
    • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/... — chart transforms, monthly vs legacy fallback handling.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ❓ Inconclusive While the PR contains several UI polish changes beyond LFXV2-845 (meeting card hover states, pending actions styling, button refactoring, heading styles, committee label updates), these enhancements are reasonable complementary improvements to the dashboard. However, some changes like the Data Copilot component refactoring appear tangential to the core metrics integration objective. Review scope creep in non-core areas: Data Copilot button refactoring, global SCSS heading styles, and committee label refactoring may warrant separate PRs to maintain focused changes for core API integration work.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding metrics API integration and monthly charts to dashboards, which is the primary focus of the changeset.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, covering API endpoints, frontend changes, UI polish, and code quality improvements across multiple files.
Linked Issues check ✅ Passed The PR successfully implements all objectives from LFXV2-845: adds getCompanyBusFactor API endpoint, replaces hardcoded constant with live API data, updates UI colors to blue theme, adds FoundationCompanyBusFactorResponse interface, and integrates data into foundation health dashboard.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/LFXV2-845

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2e2b151 and c28def1.

📒 Files selected for processing (1)
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.html (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.html

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
apps/lfx-one/src/server/utils/persona-helper.ts (3)

42-47: Consider DEBUG level for the high-level "start" log

The operation-level log at function entry is useful, but it’s an intent/entry log rather than a completion or data-retrieval event. Per the server logging guidelines (INFO for completions/successful retrieval, DEBUG for internal operations and intent), this might be better as req.log.debug to reduce noise while keeping traceability.


69-75: Tune per-category logs to DEBUG or consolidate to reduce verbosity

The new per-category logs (“Checking committee category” and “Found committee memberships”) are helpful for tracing, but they’ll emit at least one INFO log per category per request. Since these represent internal iteration rather than a completed business operation, consider:

  • Using req.log.debug instead of info for the “Checking committee category” and possibly the “Found committee memberships” message, or
  • Consolidating the membership-count information into the existing summary log that already includes username, category, and persona.

This would align better with the guideline of reserving INFO for completed operations and successful retrievals while keeping detailed traces at DEBUG.

Also applies to: 78-85


104-111: Revisit log level for "no committee memberships found" cases

Logging “No committee memberships found” for each category at INFO could be noisy if it’s common for users to lack memberships in most categories. If “no memberships” is an expected state rather than an anomaly, consider downgrading to debug so INFO remains focused on positive results and higher-level events.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 08a4c44 and f150983.

📒 Files selected for processing (11)
  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html (2 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (5 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (11 hunks)
  • apps/lfx-one/src/app/shared/services/analytics.service.ts (6 hunks)
  • apps/lfx-one/src/server/controllers/analytics.controller.ts (5 hunks)
  • apps/lfx-one/src/server/routes/analytics.route.ts (2 hunks)
  • apps/lfx-one/src/server/services/organization.service.ts (4 hunks)
  • apps/lfx-one/src/server/utils/persona-helper.ts (3 hunks)
  • packages/shared/src/constants/chart-options.constants.ts (2 hunks)
  • packages/shared/src/constants/dashboard-metrics.constants.ts (2 hunks)
  • packages/shared/src/interfaces/analytics-data.interface.ts (7 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Always use direct imports for standalone components - no barrel exports
Use TypeScript interfaces instead of union types for better maintainability
Do not nest ternary expressions
Prefer interface for defining object shapes in TypeScript
Use path mappings and import aliases as configured in tsconfig.json for imports

Files:

  • apps/lfx-one/src/server/utils/persona-helper.ts
  • packages/shared/src/constants/chart-options.constants.ts
  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
  • apps/lfx-one/src/server/services/organization.service.ts
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/constants/dashboard-metrics.constants.ts
  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
**/*.{html,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add data-testid attributes when creating new components for reliable test targeting

Files:

  • apps/lfx-one/src/server/utils/persona-helper.ts
  • packages/shared/src/constants/chart-options.constants.ts
  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
  • apps/lfx-one/src/server/services/organization.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/constants/dashboard-metrics.constants.ts
  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: License headers are required on all source files
Prepend 'Generated with Claude Code (https://claude.ai/code)' if assisted with the code

Files:

  • apps/lfx-one/src/server/utils/persona-helper.ts
  • packages/shared/src/constants/chart-options.constants.ts
  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
  • apps/lfx-one/src/server/services/organization.service.ts
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • packages/shared/src/constants/dashboard-metrics.constants.ts
  • apps/lfx-one/src/app/shared/services/analytics.service.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
apps/**/**/server/**/*.{ts,js}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/**/**/server/**/*.{ts,js}: Use Pino for structured JSON logs with sensitive data redaction in all backend services
Always use err field for errors to leverage Pino's error serializer - correct: req.log.error({ err: error, ...metadata }, 'message')
Log INFO level for business operation completions (created, updated, deleted) and successful data retrieval
Log WARN level for error conditions leading to exceptions and data quality issues
Log DEBUG level for internal operations, preparation steps, and intent statements
Log ERROR level for system failures, unhandled exceptions, and critical errors

Files:

  • apps/lfx-one/src/server/utils/persona-helper.ts
  • apps/lfx-one/src/server/services/organization.service.ts
  • apps/lfx-one/src/server/routes/analytics.route.ts
  • apps/lfx-one/src/server/controllers/analytics.controller.ts
packages/shared/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

All shared types, interfaces, and constants are centralized in @lfx-one/shared package

Files:

  • packages/shared/src/constants/chart-options.constants.ts
  • packages/shared/src/constants/dashboard-metrics.constants.ts
  • packages/shared/src/interfaces/analytics-data.interface.ts
**/*.component.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use Angular 19 zoneless change detection with signals for component state management

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

Use data-testid naming convention - [section]-[component]-[element] for hierarchical structure

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html
apps/**/**/server/**/*controller*.{ts,js}

📄 CodeRabbit inference engine (CLAUDE.md)

All controller functions must use Logger helper methods: Logger.start(), Logger.success(), Logger.error(), Logger.warning(), Logger.validation()

Files:

  • apps/lfx-one/src/server/controllers/analytics.controller.ts
🧬 Code graph analysis (5)
packages/shared/src/constants/chart-options.constants.ts (1)
packages/shared/src/constants/colors.constants.ts (1)
  • lfxColors (9-106)
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (2)
packages/shared/src/interfaces/dashboard-metric.interface.ts (1)
  • CompanyBusFactor (139-148)
packages/shared/src/interfaces/analytics-data.interface.ts (1)
  • FoundationCompanyBusFactorResponse (1949-1969)
apps/lfx-one/src/app/shared/services/analytics.service.ts (2)
packages/shared/src/interfaces/analytics-data.interface.ts (5)
  • OrganizationMaintainersResponse (1742-1774)
  • OrganizationContributorsResponse (1858-1885)
  • CertifiedEmployeesResponse (1489-1516)
  • OrganizationEventAttendanceMonthlyResponse (281-319)
  • FoundationCompanyBusFactorResponse (1949-1969)
apps/lfx-one/src/server/helpers/logger.ts (1)
  • error (52-65)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (4)
packages/shared/src/interfaces/analytics-data.interface.ts (4)
  • OrganizationMaintainersResponse (1742-1774)
  • OrganizationContributorsResponse (1858-1885)
  • CertifiedEmployeesResponse (1489-1516)
  • OrganizationEventAttendanceMonthlyResponse (281-319)
packages/shared/src/constants/colors.constants.ts (1)
  • lfxColors (9-106)
packages/shared/src/utils/color.utils.ts (1)
  • hexToRgba (28-56)
packages/shared/src/interfaces/dashboard-metric.interface.ts (1)
  • DashboardMetricCard (29-116)
apps/lfx-one/src/server/controllers/analytics.controller.ts (2)
apps/lfx-one/src/server/helpers/logger.ts (2)
  • Logger (10-129)
  • error (52-65)
apps/lfx-one/src/server/errors/index.ts (1)
  • ServiceValidationError (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Agent
🔇 Additional comments (41)
packages/shared/src/constants/chart-options.constants.ts (3)

16-37: LGTM! Good refactoring to centralize tooltip styling.

This extraction eliminates duplication and makes tooltip styling consistent across all chart types.


39-52: LGTM! BASE_TOOLTIP_CONFIG correctly refactored.

The spread of BASE_TOOLTIP_STYLE properly consolidates styling while maintaining the index-based hover behavior.


66-81: LGTM! STYLED_TOOLTIP_CONFIG properly simplified.

Inheriting from BASE_TOOLTIP_CONFIG while overriding displayColors: true and footerColor is the correct approach for multi-dataset tooltips.

packages/shared/src/constants/dashboard-metrics.constants.ts (2)

104-133: LGTM! Mock chart data correctly replaced with EMPTY_CHART_DATA.

Replacing inline mock data with EMPTY_CHART_DATA for Active Contributors, Maintainers, Event Attendees, Event Speakers, and Certified Employees aligns with the PR objective to populate these metrics from live API data.


4-4: Import change aligns with PR objective to replace hardcoded bus factor data.

Verification confirms all COMPANY_BUS_FACTOR constant references have been removed from the codebase. The CompanyBusFactor type remains intentionally in use within interface definitions and the foundation-health component for API data structure consistency, which is appropriate for the live API integration approach. The import removal from this file is correct.

packages/shared/src/interfaces/analytics-data.interface.ts (5)

200-319: LGTM! Well-structured monthly data interfaces.

The new OrganizationEventAttendanceMonthlyRow and OrganizationEventAttendanceMonthlyResponse interfaces are well-documented with clear field descriptions. The separation of attendeesMonthlyData and speakersMonthlyData in the response aligns well with the UI charting requirements.


1428-1516: LGTM! CertifiedEmployeesMonthlyRow and updated CertifiedEmployeesResponse.

The monthly row interface includes all necessary fields for cumulative calculations, and the updated response properly includes monthlyData and monthlyLabels for chart visualization.


1676-1774: LGTM! OrganizationMaintainersMonthlyRow and updated response.

The maintainers monthly interface properly captures active maintainers and projects per month with yearly aggregates. The response structure with monthlyData/monthlyLabels is consistent with other updated interfaces.


1802-1885: LGTM! OrganizationContributorsMonthlyRow and updated response.

The contributors monthly interface includes UNIQUE_CONTRIBUTORS and TOTAL_ACTIVE_CONTRIBUTORS for proper monthly tracking. The response correctly omits the projects field that exists in OrganizationMaintainersResponse, which aligns with the different data model for contributors.


1887-1969: LGTM! FoundationCompanyBusFactorRow and Response interfaces.

The bus factor interfaces properly capture concentration risk metrics. The response interface maps cleanly to the existing CompanyBusFactor UI interface format, ensuring backward compatibility with the dashboard visualization.

apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html (2)

10-10: LGTM! DataCopilot configuration update.

Setting [includeOrganizationId]="false" and [includeOrganizationName]="false" appropriately configures the component for foundation-level context where organization-specific data is not relevant.


117-121: LGTM! Bus factor color update to blue theme.

The color change from previous colors to bg-blue-500 (top companies) and bg-blue-200 (other companies) aligns with the LFXV2-845 objective to update UI colors for bus factor visualization to a blue theme.

apps/lfx-one/src/server/routes/analytics.route.ts (2)

36-38: LGTM! New event-attendance-monthly endpoint.

The route follows the established pattern and is logically placed near other organization-specific analytics endpoints.


69-71: LGTM! New company-bus-factor endpoint.

The route follows the established pattern and is appropriately placed near other foundation-level endpoints.

apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts (3)

45-45: LGTM! New loading signal for company bus factor.

The companyBusFactorLoading signal follows the same pattern as other loading signals in the component.


531-554: LGTM! Company bus factor data initialization with live API integration.

The implementation correctly:

  • Sets loading state before the API call
  • Fetches data via analyticsService.getCompanyBusFactor(foundationSlug)
  • Handles errors gracefully with default zero values
  • Follows the same reactive pattern as other data initializers in this component

This replaces the previous hardcoded COMPANY_BUS_FACTOR constant with live data as per LFXV2-845 objectives.


293-310: LGTM! Transform function updated for live data.

The transformCompanyBusFactor method now constructs the busFactor object from the API response data, properly setting the loading state and value from the fetched topCompaniesCount.

apps/lfx-one/src/server/controllers/analytics.controller.ts (5)

181-218: LGTM! getCertifiedEmployees updated with foundationSlug support and monthly data logging.

The endpoint now:

  • Requires foundationSlug as a mandatory query parameter
  • Validates both parameters with clear error messages
  • Logs foundation_slug and monthly_data_points for observability
  • Follows the Logger helper pattern as per coding guidelines

260-299: LGTM! getOrganizationMaintainers updated with foundationSlug requirement.

Proper validation and logging of the new foundationSlug parameter along with monthly_data_points count.


301-339: LGTM! getOrganizationContributors updated with foundationSlug requirement.

Consistent pattern with other updated endpoints, including proper validation and logging of monthly data points.


381-420: LGTM! New getEventAttendanceMonthly endpoint.

The new endpoint:

  • Validates both accountId and foundationSlug parameters
  • Logs total_attended, total_speakers, and monthly_data_points
  • Follows the established controller pattern with Logger helpers

788-818: LGTM! New getCompanyBusFactor endpoint.

The endpoint:

  • Only requires foundationSlug (no accountId needed since it's foundation-level data)
  • Logs top_companies_count and top_companies_percentage for observability
  • Follows established patterns with proper error handling
apps/lfx-one/src/app/shared/services/analytics.service.ts (5)

121-136: LGTM! getOrganizationMaintainers updated with foundationSlug parameter.

The method signature, HTTP params, and error fallback all properly include monthlyData and monthlyLabels arrays, matching the updated OrganizationMaintainersResponse interface.


144-158: LGTM! getOrganizationContributors updated with foundationSlug parameter.

Consistent implementation with proper error fallback containing monthlyData and monthlyLabels.


195-209: LGTM! getCertifiedEmployees updated with foundationSlug parameter.

The error fallback correctly includes monthlyData and monthlyLabels arrays matching the updated interface.


255-278: LGTM! New getEventAttendanceMonthly method.

The method:

  • Accepts accountId and foundationSlug parameters
  • Returns OrganizationEventAttendanceMonthlyResponse
  • Error fallback includes all required fields: totalAttended, totalSpeakers, accountId, accountName, attendeesMonthlyData, speakersMonthlyData, monthlyLabels

371-388: LGTM! New getCompanyBusFactor method.

The method properly returns FoundationCompanyBusFactorResponse with appropriate default values in the error fallback.

apps/lfx-one/src/server/services/organization.service.ts (5)

105-148: LGTM! getCertifiedEmployees updated with foundation filtering and monthly data.

The implementation:

  • Uses parameterized SQL with accountId and foundationSlug
  • Computes cumulative certifications via SQL window function
  • Extracts yearly totals from the first row
  • Formats month labels using toLocaleDateString

201-243: LGTM! getOrganizationMaintainers updated with foundation filtering.

The query structure and data transformation follow the same pattern as getCertifiedEmployees, maintaining consistency across the service.


252-291: LGTM! getOrganizationContributors updated with foundation filtering.

Consistent implementation with other monthly data methods.


344-397: LGTM! New getEventAttendanceMonthly method.

The implementation:

  • Computes cumulative attendees and speakers via SQL window functions
  • Returns separate monthly data arrays for attendees and speakers
  • Properly handles empty results with ResourceNotFoundError

405-438: LGTM! New getCompanyBusFactor method.

The SQL query:

  • Calculates other companies count and percentage in the query
  • Uses ROUND for percentage values
  • Returns a clean response mapping to the UI interface format
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (9)

57-57: LGTM! Event data source updated to monthly endpoint.

The eventAttendanceMonthlyData initialization replaces the previous events overview data, enabling monthly trend charts for event attendees and speakers.


158-204: LGTM! Maintainers data initialization with foundation guard.

The implementation:

  • Uses combineLatest to react to both accountId and foundationSlug changes
  • Returns empty default data when no foundation is selected (preventing unnecessary API calls)
  • Error fallback includes monthlyData and monthlyLabels

206-249: LGTM! Contributors data initialization with foundation guard.

Consistent pattern with maintainers data, properly handling the empty foundation case.


399-448: LGTM! New event attendance monthly data initialization.

The implementation properly:

  • Guards for empty foundation slug
  • Includes all response fields in error fallback (attendeesMonthlyData, speakersMonthlyData, monthlyLabels)
  • Uses the new getEventAttendanceMonthly service method

450-473: LGTM! Active contributors transform with conditional monthly chart data.

The ternary expression data.monthlyData.length > 0 ? {...} : metric.chartData provides graceful fallback when monthly data is unavailable.


475-499: Consider extracting singular/plural logic as a utility function.

The projectLabel logic on line 476 could be extracted if used elsewhere. However, this is a minor observation and the current implementation is clear and correct.


530-555: LGTM! Event attendees transform updated for monthly data.

The transform correctly:

  • Uses data.totalAttended for the value
  • Uses data.attendeesMonthlyData for the chart
  • Falls back to metric.chartData when monthly data is empty

557-582: LGTM! Event speakers transform updated for monthly data.

Consistent implementation with event attendees, using data.speakersMonthlyData for the chart.


584-609: LGTM! Certified employees transform updated with monthly chart data.

The chart options updated to use 'Certifications' label, and the chart data correctly uses cumulative certifications from monthlyData.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds live API integration for metrics in the foundation health and organization involvement dashboards, replacing hardcoded mock data with real-time data from Snowflake. The changes enable monthly trend visualization for organization metrics and introduce foundation-level filtering across organization endpoints.

  • Added 2 new API endpoints for company bus factor and event attendance monthly data
  • Updated 3 existing organization endpoints (maintainers, contributors, certified employees) to require foundationSlug parameter for foundation-scoped filtering
  • Implemented monthly trend charts with cumulative data visualization in the organization involvement dashboard using blue color scheme
  • Removed hardcoded mock chart data constants and replaced with live API responses

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/shared/src/interfaces/analytics-data.interface.ts Added monthly row interfaces and updated response interfaces with monthlyData and monthlyLabels arrays for chart visualization
packages/shared/src/constants/dashboard-metrics.constants.ts Removed COMPANY_BUS_FACTOR mock constant and replaced hardcoded chart data with EMPTY_CHART_DATA placeholders
packages/shared/src/constants/chart-options.constants.ts Refactored tooltip configuration by extracting BASE_TOOLTIP_STYLE constant for reusability across chart types
apps/lfx-one/src/server/utils/persona-helper.ts Added detailed logging statements for committee membership checks and persona determination
apps/lfx-one/src/server/services/organization.service.ts Updated organization metrics methods to accept foundationSlug, added SQL window functions for cumulative data, and implemented getCompanyBusFactor and getEventAttendanceMonthly methods
apps/lfx-one/src/server/routes/analytics.route.ts Registered two new route handlers for event attendance monthly and company bus factor endpoints
apps/lfx-one/src/server/controllers/analytics.controller.ts Updated controller methods to require and validate foundationSlug parameter for organization endpoints
apps/lfx-one/src/app/shared/services/analytics.service.ts Updated service methods to pass foundationSlug parameter and added getEventAttendanceMonthly and getCompanyBusFactor methods
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts Refactored data initialization to use combineLatest with foundation slug, implemented monthly chart data visualization with blue theme, and added early returns for empty foundation selection
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.ts Integrated live company bus factor API data replacing hardcoded mock constant
apps/lfx-one/src/app/modules/dashboards/components/foundation-health/foundation-health.component.html Updated bus factor visualization colors from gray to blue theme and adjusted data copilot to exclude organization parameters

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Remove deprecated code that is no longer used after dashboard refactoring:

- Frontend: Remove getOrganizationEventsOverview and getProjects methods
- Backend: Remove corresponding routes, controller and service methods
- Interfaces: Remove 7 unused row/response types replaced by monthly versions

Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Asitha de Silva <asithade@gmail.com>
Only show Membership Tier card when ALL filter is selected in
organization involvement section.

Generated with [Claude Code](https://claude.ai/code)

Signed-off-by: Asitha de Silva <asithade@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (2)

158-448: Well-implemented foundation filtering with opportunity to reduce duplication.

The foundation-aware data fetching correctly implements the requirement from LFXV2-847. The empty foundation guards prevent unnecessary API calls and return well-formed empty responses. The pattern is consistent across all data initialization methods.

Consider extracting the empty foundation handling into a reusable helper to reduce duplication:

private handleEmptyFoundation<T>(
  loadingSignal: WritableSignal<boolean>,
  emptyResponse: T
): Observable<T> {
  loadingSignal.set(false);
  return of(emptyResponse);
}

Then use it in each method:

if (!foundationSlug) {
  return this.handleEmptyFoundation(this.maintainersLoading, {
    maintainers: 0,
    projects: 0,
    accountId: '',
    accountName: '',
    monthlyData: [],
    monthlyLabels: [],
  } as OrganizationMaintainersResponse);
}

This would eliminate ~25 lines of duplicated guard logic across the five methods.


450-473: Excellent monthly data integration with consistent chart patterns.

The conditional rendering of monthly data with fallbacks to metric.chartData is well-implemented. The chart configurations follow consistent patterns: bar charts for contributors/maintainers with rounded corners, and line charts with area fill for events and certifications. The use of lfxColors.blue[500] aligns with the blue theme objective from LFXV2-845.

Minor UX improvement for the maintainers subtitle (line 481): when data.projects is 0, the subtitle reads "Across 0 projects" which is grammatically awkward. Consider:

 private transformMaintainers(data: OrganizationMaintainersResponse, metric: DashboardMetricCard): DashboardMetricCard {
   const projectLabel = data.projects === 1 ? 'project' : 'projects';
   return {
     ...metric,
     loading: this.maintainersLoading(),
     value: data.maintainers.toString(),
-    subtitle: `Across ${data.projects} ${projectLabel}`,
+    subtitle: data.projects > 0 ? `Across ${data.projects} ${projectLabel}` : 'No projects yet',
     chartOptions: this.createBarChartOptions('Maintainers'),

Also applies to: 475-499, 530-555, 557-582, 584-609

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fc0f41e and d87749c.

📒 Files selected for processing (1)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (11 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Always use direct imports for standalone components - no barrel exports
Use TypeScript interfaces instead of union types for better maintainability
Do not nest ternary expressions
Prefer interface for defining object shapes in TypeScript
Use path mappings and import aliases as configured in tsconfig.json for imports

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
**/*.{html,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add data-testid attributes when creating new components for reliable test targeting

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: License headers are required on all source files
Prepend 'Generated with Claude Code (https://claude.ai/code)' if assisted with the code

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
**/*.component.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use Angular 19 zoneless change detection with signals for component state management

Files:

  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
🧬 Code graph analysis (1)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (4)
packages/shared/src/interfaces/analytics-data.interface.ts (4)
  • OrganizationMaintainersResponse (1595-1627)
  • OrganizationContributorsResponse (1685-1712)
  • CertifiedEmployeesResponse (1368-1395)
  • OrganizationEventAttendanceMonthlyResponse (281-319)
packages/shared/src/constants/colors.constants.ts (1)
  • lfxColors (9-106)
packages/shared/src/utils/color.utils.ts (1)
  • hexToRgba (28-56)
packages/shared/src/interfaces/dashboard-metric.interface.ts (1)
  • DashboardMetricCard (29-116)
🔇 Additional comments (3)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (3)

18-26: LGTM: Import of monthly event attendance interface.

The addition of OrganizationEventAttendanceMonthlyResponse aligns with the PR objective to add monthly trend data for event attendance. The import follows the project's conventions using path aliases and type-only imports.


399-448: Well-executed refactoring to unified monthly event attendance endpoint.

The refactoring from separate event data sources to a single eventAttendanceMonthlyData source that provides both attendee and speaker monthly trends is an excellent design choice. Both cards now consume the same API response but extract different series (attendeesMonthlyData vs speakersMonthlyData), reducing API calls while maintaining separate visualizations.

This implementation perfectly aligns with PR objective LFXV2-846: "Refactor event attendees and speakers cards to use monthly trend charts and separate series."

Also applies to: 530-582


638-668: LGTM: Type-safe chart option factories.

The chart option factory methods properly extend base configurations and provide type-safe tooltip customization. The separation of bar and line chart options maintains clarity and follows the DRY principle.

- Update button styling to pill shape with solid blue background
- Replace microchip-ai icon with Font Awesome stacked icons
- Use fa-comment with fa-sparkle overlay for composite icon

LFXV2-845

Signed-off-by: Asitha de Silva <asithade@gmail.com>
- Replace hardcoded "Committee" with COMMITTEE_LABEL constant
- Update committee-members component header and empty state
- Update meeting registrants manager status filter
- Update registrant modal info message and tooltip

LFXV2-845

Signed-off-by: Asitha de Silva <asithade@gmail.com>
LFXV2-845

- Add hover border effects to meeting cards and pending actions
- Use distinct colors for metrics charts (emerald, amber, violet)
- Remove redundant Today/Upcoming section headers from meetings
- Update LFX Lens button to outlined style with lighter icons
- Remove redundant leading-normal from heading styles

Signed-off-by: Asitha de Silva <asithade@gmail.com>
LFXV2-845

Update Contributors Mentored chart tooltip to match Active Contributors
format with properly formatted date labels (e.g., "Dec 1, 2024") and
custom tooltip callbacks.

Signed-off-by: Asitha de Silva <asithade@gmail.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (6)
apps/lfx-one/src/app/shared/components/data-copilot/data-copilot.component.html (1)

28-28: Consider enhancing data-testid hierarchy for nested elements.

The data-testid="data-copilot-iframe-container" could use a more hierarchical naming pattern to reflect its parent context. Following the [section]-[component]-[element] convention, consider: data-testid="data-copilot-drawer-iframe-container".

apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.html (1)

20-27: Tooltip dynamic label is fine; consider aligning the other tooltip

The delete button tooltip using committeeLabel.singular + ' members…' is functionally correct and matches the dynamic labeling strategy.

For consistency, you may also want to update the submit button tooltip on line 68 ('Committee member details…') to use committeeLabel.singular rather than hardcoded “Committee”.

apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts (1)

42-48: committeeLabel field wiring is straightforward; could be readonly

public committeeLabel = COMMITTEE_LABEL; exposes the labels cleanly to the template and matches patterns in other components.

If you want to tighten intent, you could declare it as readonly:

public readonly committeeLabel = COMMITTEE_LABEL;

But it’s not required for correctness.

apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts (1)

63-68: committeeLabel exposure is correct; readonly would further clarify intent

Exposing committeeLabel = COMMITTEE_LABEL gives the template access to both singular and plural labels and matches the new HTML bindings.

As with the modal, you might optionally mark it readonly:

public readonly committeeLabel = COMMITTEE_LABEL;

to signal that it’s configuration, not mutable state.

apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (2)

158-204: Foundation-gated loaders with monthly trend defaults for maintainers & contributors look solid

Using combineLatest([selectedAccountId$, selectedFoundationSlug$]) with switchMap gives correct reactivity on both account and foundation changes. The early !foundationSlug guard avoids unnecessary API calls and returns well-formed empty OrganizationMaintainersResponse/OrganizationContributorsResponse objects including monthlyData/monthlyLabels, which keeps downstream chart logic simple. Error handling also returns the same empty shape and always clears the loading flags.

If you find yourself adding more such loaders, consider extracting shared “empty response” factory functions to reduce duplication and keep default shapes centralized.

Also applies to: 206-249


399-448: Event attendance monthly data loader matches new API contract

initializeEventAttendanceMonthlyData correctly:

  • Gates on foundationSlug and skips API calls when none is selected.
  • Uses getEventAttendanceMonthly(accountId, foundationSlug) to fetch data.
  • Returns a full default OrganizationEventAttendanceMonthlyResponse (totals, account info, attendees/speakers monthly arrays, labels) for both the no-foundation and error paths.
    This directly matches the shared interface and provides a stable shape for the event attendee/speaker transforms.

You could optionally move the default empty object into a const EMPTY_EVENT_ATTENDANCE_RESPONSE to avoid repeating the same literal in three places.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d87749c and 2e2b151.

📒 Files selected for processing (13)
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.html (2 hunks)
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts (2 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.html (0 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (11 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (2 hunks)
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.html (1 hunks)
  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts (2 hunks)
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.html (2 hunks)
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts (2 hunks)
  • apps/lfx-one/src/app/shared/components/data-copilot/data-copilot.component.html (1 hunks)
  • apps/lfx-one/src/styles.scss (1 hunks)
💤 Files with no reviewable changes (1)
  • apps/lfx-one/src/app/modules/dashboards/components/my-meetings/my-meetings.component.html
✅ Files skipped from review due to trivial changes (2)
  • apps/lfx-one/src/app/modules/dashboards/components/dashboard-meeting-card/dashboard-meeting-card.component.html
  • apps/lfx-one/src/styles.scss
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Always use direct imports for standalone components - no barrel exports
Use TypeScript interfaces instead of union types for better maintainability
Do not nest ternary expressions
Prefer interface for defining object shapes in TypeScript
Use path mappings and import aliases as configured in tsconfig.json for imports

Files:

  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts
**/*.{html,ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always add data-testid attributes when creating new components for reliable test targeting

Files:

  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.html
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts
  • apps/lfx-one/src/app/shared/components/data-copilot/data-copilot.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.html
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js,jsx}: License headers are required on all source files
Prepend 'Generated with Claude Code (https://claude.ai/code)' if assisted with the code

Files:

  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts
**/*.component.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use Angular 19 zoneless change detection with signals for component state management

Files:

  • apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts
  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts
  • apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts
**/*.html

📄 CodeRabbit inference engine (CLAUDE.md)

Use data-testid naming convention - [section]-[component]-[element] for hierarchical structure

Files:

  • apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.html
  • apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html
  • apps/lfx-one/src/app/shared/components/data-copilot/data-copilot.component.html
  • apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.html
  • apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.html
🧬 Code graph analysis (5)
apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts (1)
packages/shared/src/constants/committees.constants.ts (1)
  • COMMITTEE_LABEL (16-19)
apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts (1)
packages/shared/src/constants/committees.constants.ts (1)
  • COMMITTEE_LABEL (16-19)
apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts (1)
packages/shared/src/constants/committees.constants.ts (1)
  • COMMITTEE_LABEL (16-19)
apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (3)
packages/shared/src/interfaces/analytics-data.interface.ts (4)
  • OrganizationMaintainersResponse (1595-1627)
  • OrganizationContributorsResponse (1685-1712)
  • CertifiedEmployeesResponse (1368-1395)
  • OrganizationEventAttendanceMonthlyResponse (281-319)
packages/shared/src/constants/colors.constants.ts (1)
  • lfxColors (9-106)
packages/shared/src/utils/color.utils.ts (1)
  • hexToRgba (28-56)
apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (2)
packages/shared/src/utils/date-time.utils.ts (1)
  • parseLocalDateString (52-65)
packages/shared/src/constants/chart-options.constants.ts (1)
  • BASE_LINE_CHART_OPTIONS (87-100)
🔇 Additional comments (21)
apps/lfx-one/src/app/modules/meetings/components/meeting-card/meeting-card.component.html (1)

5-5: Styling enhancement looks good.

The border, rounded corners, and hover state improve visual hierarchy and interactivity without affecting component logic. The conditional padding via [ngClass] remains properly scoped, and the styling aligns with the PR's blue theme updates.

apps/lfx-one/src/app/modules/dashboards/components/pending-actions/pending-actions.component.html (1)

4-99: Styling improvements and data-testid coverage look good.

The changes properly enhance the pending-actions component with refined spacing, border styling, and hover states while maintaining consistent color theming throughout. All sections have appropriate data-testid attributes following the hierarchical naming convention ([section]-[component]-[element]), ensuring reliable test targeting without compromising functionality.

The color mappings (container, header, icon, text) are well-coordinated and align with the broader UI theming updates mentioned in the PR objectives.

apps/lfx-one/src/app/shared/components/data-copilot/data-copilot.component.html (1)

11-15: Updated button styling and icon content LGTM.

The styling updates (white background with blue border/text and hover effect) and the decorative font-awesome stack (comment + sparkle) look good and align with the PR's UI enhancement objectives.

apps/lfx-one/src/app/modules/dashboards/components/recent-progress/recent-progress.component.ts (1)

458-473: Tooltip implementation looks good.

The custom tooltip callbacks are implemented correctly. The title callback returns the pre-formatted label directly (consistent with the formatted chartLabels from line 444), and the label callback properly formats the count using toLocaleString().

apps/lfx-one/src/app/modules/meetings/components/meeting-registrants-manager/meeting-registrants-manager.component.ts (2)

13-13: COMMITTEE_LABEL import is consistent with shared constants usage

Importing COMMITTEE_LABEL from the shared constants alias matches how other committee-related components are wired and avoids duplicating literals. No issues here.


79-83: Dynamic committee label for status filter looks good

Switching "Committee Members" to COMMITTEE_LABEL.singular + ' Members' keeps the filter value 'member' stable while making the label consistent with the new dynamic committee naming. This should remain compatible with the status switch in initFilteredRegistrants.

apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.html (2)

8-8: Header now correctly uses dynamic committee label

Using {{ committeeLabel.singular }} Members ties the title to the shared COMMITTEE_LABEL config and keeps the template aligned with other committee UIs.


176-181: Empty-state copy aligned with dynamic labeling

This {{ committeeLabel.singular }} doesn't have any members yet. reuses the same label source as the header, which is good for consistency and future re-labeling.

apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.html (1)

8-13: Committee info message correctly wired to shared labels

The info banner now uses committeeLabel.singular/plural, so any future rename (e.g., “Group”) will automatically reflect here without string duplication.

apps/lfx-one/src/app/modules/meetings/components/registrant-modal/registrant-modal.component.ts (1)

9-9: Importing COMMITTEE_LABEL from shared constants is appropriate

This keeps the modal in sync with the central committee label definition and avoids local magic strings.

apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.ts (1)

15-15: Shared COMMITTEE_LABEL import keeps component aligned with global config

Pulling COMMITTEE_LABEL from the shared constants module is consistent with other committee-related components and avoids string drift.

apps/lfx-one/src/app/modules/dashboards/components/organization-involvement/organization-involvement.component.ts (10)

18-26: New OrganizationEventAttendanceMonthlyResponse import is correct and aligned with interfaces

The added OrganizationEventAttendanceMonthlyResponse import matches the shared interface definition and is used consistently in the new event attendance monthly logic below. No issues here.


49-57: Consistent use of signals and derived eventAttendanceMonthlyData

Hooking selectedFoundationSlug$ alongside selectedAccountId$ and introducing eventAttendanceMonthlyData as a dedicated signal keeps the data flow consistent with the other metrics and supports the new foundation-scoped behavior.


120-126: Event attendee/speaker cards correctly bound to monthly attendance data

Wiring both initializeEventAttendeesCard and initializeEventSpeakersCard to eventAttendanceMonthlyData() centralizes the event metrics source and ensures both cards stay in sync with the same response. This matches the new monthly endpoint design.


136-155: Primary metrics filtering remains simple and extensible

The initializePrimaryMetrics logic stays straightforward: all cards are categorized once and filtered by selectedFilter, with no nested ternaries. This is easy to extend if new categories/cards are added later.


317-360: Certified employees loader correctly switches to foundationSlug and supports monthly trends

The certified employees pipeline mirrors the other loaders: it requires foundationSlug, short-circuits with an empty object when missing, and returns a consistent empty shape (including monthlyData/monthlyLabels) on error and as initialValue. This aligns with the updated CertifiedEmployeesResponse interface and avoids null checks in the transform.


450-473: Active contributors chart now correctly leverages monthly trend data

The transformActiveContributors implementation:

  • Keeps existing value/subtitle semantics.
  • Switches chartData to a bar chart built from monthlyData/monthlyLabels when available, using blue tokens via lfxColors and hexToRgba.
  • Falls back to metric.chartData otherwise, preserving existing visuals where the backend doesn’t yet send monthly arrays.
    This is a clean, non-breaking way to introduce monthly trend charts.

475-499: Maintainers pluralization and monthly bar chart integration are well done

The projectLabel singular/plural logic avoids “1 projects” and improves UX, and the chart logic mirrors contributors: use monthly bar data when present, otherwise fall back to the preconfigured chart. Color usage (blue scale) is consistent with the rest of the UI.


530-555: Event attendees now use monthly cumulative trends with appropriate styling

transformEventAttendees correctly:

  • Uses totalAttended for the main metric.
  • Builds a line chart from attendeesMonthlyData and monthlyLabels, with emerald color tokens and a subtle filled area.
  • Safely falls back to the existing metric.chartData when no monthly data is provided.
    This aligns with the OrganizationEventAttendanceMonthlyResponse contract and the PR’s monthly trend objectives.

557-582: Event speakers monthly trend chart mirrors attendees behavior

The speakers transform:

  • Takes totalSpeakers as the primary value.
  • Uses speakersMonthlyData with the shared monthlyLabels for the line chart.
  • Applies amber theming for clear visual distinction from attendees while preserving the same chart behavior and fallbacks.
    The symmetry between attendees and speakers will make maintenance and future tweaks straightforward.

584-608: Certified employees monthly certifications chart is consistent with other trend charts

The updated transformCertifiedEmployees:

  • Keeps the existing value/subtitle semantics (employees vs total certifications).
  • Switches chartOptions to a line chart labeled “Certifications”.
  • Renders monthly certification trends using monthlyData/monthlyLabels when available, with violet theming and the same chart styling (fill, tension, border width, no points) as other line charts.
    Fallback to metric.chartData ensures backward compatibility if monthly data isn’t present.

Signed-off-by: Asitha de Silva <asithade@gmail.com>
MONTHLY_CERTIFIED_EMPLOYEES,
TOTAL_CERTIFICATIONS,
TOTAL_CERTIFIED_EMPLOYEES,
SUM(MONTHLY_CERTIFICATIONS) OVER (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make a note to improve our models to include the cumulative data. Thanks @asithade !

@asithade asithade merged commit f62101e into main Dec 1, 2025
6 checks passed
@asithade asithade deleted the feat/LFXV2-845 branch December 1, 2025 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants